#ifndef UF_H
#define UF_H
#include "Bool.h"
#include "error.h"

typedef struct s_Uf *union_find;
typedef int tufalpha;
typedef int tufset;
typedef int tufpos;
typedef int cant;

/* constructor 
   PRE:{max >=0 && �Que haya memoria!(pedirle a Raynhold que complete esta pre)}
   u=uf_create(max)
   POS:{u -> max = max && <V i : 0<=i<max : (u -> sets)[i] = 0>}
*/
union_find
uf_create(const tufpos max);

/* agrega singulete 
   PRE:{uf != NULL && uf= Uf && 0 <= el < max}
   uf_add_singulete(uf,el)
   POS:{(Uf -> sets)[el] = 0 => (uf -> sets)[el] = -1}
*/
void
uf_add_singulete(union_find uf, const tufalpha el); 

/*
   PRE:{uf != NULL && 0<= el <uf -> max}
   b=is_rep(uf,el)
   POS:{}
*/
Bool
is_rep(const union_find uf, const tufalpha el); 

/* busca conjunto a partir
de un elemento que le pertenece 
(find con compresi�n de caminos)
*/
tufset
uf_find(union_find uf, const tufalpha el); 

/* union
de los conjuntos 
      PRE: {uf != NULL && s1 != s2 && is_rep(s1) && is_rep(s2)}
      uf(uf,s1,s2);
      POS:{(uf -> sets[s1] <= uf -> sets[s2]) => (uf -> sets[s1] = uf -> sets[s1] +  uf -> sets[s2]) && uf -> sets[s2] = s1)
                                    || 
           (uf -> sets[s2] < uf -> sets[s1]) => (uf -> sets[s2] = uf -> sets[s2] +  uf -> sets[s1]) && uf -> sets[s1] = s2)}
*/
void
uf_union(union_find uf, const tufset s1, const tufset s2);

/* hay solo un conjunto? */
Bool
uf_oneset(const union_find uf); 

/* destructor */
union_find
uf_destroy(union_find uf); 

/* Devuelve el n� de componentes conexas */
int
uf_ccc (union_find uf);

/*void print(union_find uf);*/

#endif
